package com.easycoding.ums.security.shiro.filter;

import java.util.Date;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.easycoding.framework.web.online.SessionUsers;
import com.easycoding.ums.security.shiro.SessionKey;
import com.easycoding.ums.security.shiro.expand.LoginExpandOperator;
import com.easycoding.ums.security.shiro.token.CaptchaUsernamePasswordToken;
import com.easycoding.ums.system.bo.UserTicket;
import com.easycoding.ums.system.entity.User;
import com.easycoding.ums.system.service.UserService;



/**
 * 自定义登录验证过滤器
 * @author Wangjk
 * @Version 1.0
 * @Date 2013-4-5
 */
public class LoginAuthenticationFilter extends FormAuthenticationFilter implements ApplicationContextAware{

	private static ApplicationContext applicationContext;
	
	/**
	 * 用户管理服务
	 */
	@Resource(name = "umsUserService")
	private UserService userService;
	
	public static final String DEFAULT_USERNAME_PARAM = "username";
    public static final String DEFAULT_PASSWORD_PARAM = "password";
	public static final String DEFAULT_CAPTCHA_PARAM = "captcha";
	public static final String DEFAULT_REMEMBER_ME_PARAM = "rememberMe";
	
	private String captchaParam = DEFAULT_CAPTCHA_PARAM;
	
	public String getCaptchaParam() {
		return captchaParam;
	}
	
	public void setCaptchaParam(String captchaParam) {
		this.captchaParam = captchaParam;
	}

	protected String getCaptcha(ServletRequest request) {
		return WebUtils.getCleanParam(request, getCaptchaParam());
	}
	
	/**
	 * 创建令牌
	 */
	protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
		String username = getUsername(request);
		String password = getPassword(request);
		password = password==null?"":password;
		String captcha = getCaptcha(request);
		boolean rememberMe = isRememberMe(request);
		String host = getHost(request);
		return new CaptchaUsernamePasswordToken(username, password.toCharArray(), rememberMe, host, captcha);
	}

	/**
	 * 登录成功时
	 * 设置用户在信息和登录后的跳转页面
	 */
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
			ServletResponse response) throws Exception {
		CaptchaUsernamePasswordToken authcToken = (CaptchaUsernamePasswordToken) token;
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		UserTicket userTicket = (UserTicket)SecurityUtils.getSubject().getSession().getAttribute(SessionKey.USER);
		//记录用户登录信息
		if(userTicket != null){
			User user = userTicket.getUser();
			if(user != null){
				user.setLastLogin(new Date());//登录是时间
				//代理服务器IP
				String ip = httpServletRequest.getHeader("X-Real-IP");
		        if(ip == null)
		        	ip = httpServletRequest.getRemoteAddr();
		        user.setLoginIp(ip);//登录IP
		        user.setLoginTimes(user.getLoginTimes() == null?1:(user.getLoginTimes()+1));//登录次数
		        this.userService.updateUser(user);
			}
			//设置用户在线信息
			HttpSession session  = httpServletRequest.getSession();
			String userName = authcToken.getUsername();
			session.setAttribute(userName, SessionUsers.getInstance());
		}
		String successUrl = this.getSuccessUrl();
		//未设置successUrl时,使用shiro的跳转机制
		if(StringUtils.isEmpty(successUrl) || successUrl.equals("/")){
			issueSuccessRedirect(request, response);
		}
		else{//设置successUrl时，强制跳转到successUrl;
			HttpServletResponse httpServletResponse= (HttpServletResponse) response;
			httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+successUrl);
		}
		//自定义扩展操作
//		if(expandOperator != null ){
//			expandOperator.expandOperate(authcToken, subject, httpServletRequest, response);
//		}
		this.expandOperate(authcToken, subject, httpServletRequest, response);
		return true;
	}
	
	/**
	 * 自定义用户验证
	 * @param authcToken
	 * @return 返回true 代表验证通过，返回false 代表验证失败
	 */
	private void expandOperate(AuthenticationToken token, Subject subject, ServletRequest request,
			ServletResponse response){
		// 按类型获取上下文中的对象  
        Map<String, LoginExpandOperator> map = applicationContext.getBeansOfType(LoginExpandOperator.class, true, true);  
		for (LoginExpandOperator operator : map.values()) {  
	    	operator.expandOperate(token, subject, request, response);
		}  
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		LoginAuthenticationFilter.applicationContext = applicationContext;
	}
}
